/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.db;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.sql.*;

import blueprint4j.utils.*;

public class FieldUnique extends FieldString implements FieldId {
    private static DBConnection dbconnection = null;
    
    private static final String ZEROS = "00000000000000000000";
    private Index.UniqueIndex uni_index_id= null;
    private static String server_id_string = null;
    private boolean set_once = false;
    
    /**
     * public Field( String p_name, String p_description, boolean p_key_field
     *
     * Name: Name of field -> equivalent to table.field_name
     * Description: Description of field
     * key_field: Is this field a key field in the table (index field)
     */
    public FieldUnique( String p_name, int p_field_type , String p_description, Entity entity) {
        super( p_name,(Field.FIELD_NOT_NULL | p_field_type | Field.FIELD_KEY) , p_description, 26,entity);
        entity.setFieldId(this);
        uni_index_id = new Index.UniqueIndex("uni_index_id",new Field[]{this},entity);
    }
    
    public Field newInstance(Entity entity) {
        return new FieldUnique(getName(),getFieldType(),getDescription(),entity);
    }
    
    public void set(String value,boolean allow_duplicate_set) {
        if (!set_once || allow_duplicate_set) {
            super.set(value);
            set_once = true;
        } else {
        	if (!((get()==null && value==null) || (get()!=null && get().equals(value)))){
        		Log.critical.out(new Exception("ID Field value Assigned more the once"));
        	}
        }
    }
    
    public void set(String value) {
        set(value,false);
    }
    
    public void setSerializable(String p_value) {
        if ("null".equalsIgnoreCase(p_value)) {
            set((String)null);
        } else{
            set(p_value);
        }
    }
    
    public static String createIndexId(Long index)
    throws DataException {
        if (server_id_string == null) {
            // make sure that has been loaded
            if (DBTools.getServerId().equals("null")) {
                throw new DataException("You must specify the server's unique id before you can use any unique fields");
            }
            if (DBTools.getServerId().length() > 6) {
                throw new DataException("The server's unique name you specified [" + DBTools.getServerId() + "] is longer then 6 characters");
            }
            String server_id = DBTools.getServerId();
            server_id_string = ZEROS.substring(0, 6 - server_id.length()) + server_id;
        }
        return server_id_string + ZEROS.substring(0, 20 - (index.toString()).length()) + index;
    }
    
    /**
     * Builds itself from the two fields
     */
    public void set(DBConnection connection)
    throws DataException, SQLException {
        if (!isNull()) return;
        Long next_id = IndexTable.getNextIndex(getEntity());
        set(createIndexId(next_id));
    }
    
    protected void setFieldValue( ResultSet result_set )
    throws DataException {
        super.setFieldValue(result_set);
        set_once=true;
    }
    
    
    public boolean isNull() {
        return getObject() == null;
    }
    
    /**
     * Return data in a suitable SQL format
     */
    public String getSQLValue()
    throws DataException {
        if (set_once) {
            if (getObject() == null) {
                throw new DataException("ID Field with NULL value");
            }
            return "'" + get() + "'";
        }
        throw new DataException("ID Field has not been set");
    }
    
    public String get() {
        try {
            if (super.get() != null) {
                return super.get();
            } else {
                if (dbconnection == null) {
                    dbconnection = getEntity().getConnection();
                }
                set(dbconnection);
                dbconnection.commit();
                return super.get();
            }
        } catch (Throwable th) {
            Log.debug.out(th);
            return null;
        }
    }
    
    /**
     * An overloaded equals method that only accepts the correct type
     */
    public boolean equals(String value) {
        return get().equals(value);
    }
    
    public void setAsString(String value){
        set(value);
    }
    
    public void loadAfterInsert(DBConnection connection) throws SQLException {}
    
    public String getAsStringSQL() {return "'"+get()+"'";}
    
    public String getAsString() {return get();}
    
    public Long getAsLong()
    throws DataException {
        try {
            if (get() == null) {
                return null;
            }
            return new Long(get());
        } catch (Exception exception) {
            throw new DataException(exception);
        }
    }
    
    public Object getAsObject() throws DataException {return get();}
}
